//===================================================================
// 项目名 : Hbt.Cur
// 文件名 : HbtWorkflowScheduler.cs
// 创建者 : Claude
// 创建时间: 2024-12-01
// 版本号 : V0.0.1
// 描述    : 工作流定时任务调度器实现
//===================================================================

using Hbt.Application.Dtos.Workflow;
using Hbt.Application.Services.Workflow.Engine;
using Hbt.Domain.Entities.Workflow;
using Hbt.Domain.Entities.Routine.Quartz;
using Hbt.Domain.Interfaces;
using Quartz;
using Quartz.Impl;
using Newtonsoft.Json;

namespace Hbt.Application.Services.Workflow.Engine.Scheduler
{
    /// <summary>
    /// 工作流定时任务调度器实现
    /// </summary>
    public class HbtWorkflowScheduler : IHbtWorkflowScheduler
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private readonly IHbtRepositoryFactory _repositoryFactory;
        private readonly IHbtWorkflowEngine _workflowEngine;
        private readonly IHbtLogger _logger;
        private readonly IHbtCurrentUser _currentUser;
        private IScheduler _scheduler = null!;

        public HbtWorkflowScheduler(
            IHbtRepositoryFactory repositoryFactory,
            IHbtWorkflowEngine workflowEngine,
            IHbtLogger logger,
            IHbtCurrentUser currentUser)
        {
            _repositoryFactory = repositoryFactory;
            _workflowEngine = workflowEngine;
            _logger = logger;
            _currentUser = currentUser;
            _schedulerFactory = new StdSchedulerFactory();
            InitializeSchedulerAsync().Wait();
        }

        /// <summary>
        /// 创建定时任务
        /// </summary>
        public async Task<string> CreateScheduledTaskAsync(HbtWorkflowScheduledTaskDto dto)
        {
            try
            {
                // 创建定时任务实体
                var scheduledTask = new HbtQuartz
                {
                    QuartzName = dto.TaskName,
                    QuartzType = dto.TaskType,
                    QuartzCronExpression = dto.CronExpression,
                    QuartzExecuteParams = JsonConvert.SerializeObject(new { 
                        WorkflowInstanceId = dto.WorkflowInstanceId,
                        WorkflowSchemeId = dto.WorkflowSchemeId,
                        NodeId = dto.NodeId,
                        NodeName = dto.NodeName,
                        TaskData = dto.TaskData
                    }),
                    Status = 1, // 启用
                    QuartzNextRunTime = GetNextRunTime(dto.CronExpression),
                    CreateBy = _currentUser.UserId.ToString(),
                    CreateTime = DateTime.Now
                };

                await GetScheduledTaskRepository().CreateAsync(scheduledTask);

                // 创建Quartz任务
                var jobKey = new JobKey($"workflow_task_{scheduledTask.Id}");
                var triggerKey = new TriggerKey($"workflow_trigger_{scheduledTask.Id}");

                var job = JobBuilder.Create<HbtWorkflowScheduledJob>()
                    .WithIdentity(jobKey)
                    .UsingJobData("taskId", scheduledTask.Id.ToString())
                    .Build();

                var trigger = TriggerBuilder.Create()
                    .WithIdentity(triggerKey)
                    .WithCronSchedule(dto.CronExpression)
                    .Build();

                await _scheduler.ScheduleJob(job, trigger);

                _logger.Info($"定时任务创建成功，ID: {scheduledTask.Id}, 名称: {dto.TaskName}");
                return scheduledTask.Id.ToString();
            }
            catch (Exception ex)
            {
                _logger.Error($"创建定时任务失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 更新定时任务
        /// </summary>
        public async Task<bool> UpdateScheduledTaskAsync(string taskId, HbtWorkflowScheduledTaskDto dto)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return false;

                // 更新任务信息
                task.QuartzName = dto.TaskName;
                task.QuartzCronExpression = dto.CronExpression;
                task.QuartzExecuteParams = JsonConvert.SerializeObject(dto.TaskData);
                task.QuartzNextRunTime = GetNextRunTime(dto.CronExpression);
                task.UpdateBy = _currentUser.UserId.ToString();
                task.UpdateTime = DateTime.Now;

                await GetScheduledTaskRepository().UpdateAsync(task);

                // 更新Quartz任务
                var triggerKey = new TriggerKey($"workflow_trigger_{taskId}");
                var newTrigger = TriggerBuilder.Create()
                    .WithIdentity(triggerKey)
                    .WithCronSchedule(dto.CronExpression)
                    .Build();

                await _scheduler.RescheduleJob(triggerKey, newTrigger);

                _logger.Info($"定时任务更新成功，ID: {taskId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"更新定时任务失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 删除定时任务
        /// </summary>
        public async Task<bool> DeleteScheduledTaskAsync(string taskId)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return false;

                // 删除Quartz任务
                var jobKey = new JobKey($"workflow_task_{taskId}");
                var triggerKey = new TriggerKey($"workflow_trigger_{taskId}");

                await _scheduler.UnscheduleJob(triggerKey);
                await _scheduler.DeleteJob(jobKey);

                // 删除数据库记录
                await GetScheduledTaskRepository().DeleteAsync(task);

                _logger.Info($"定时任务删除成功，ID: {taskId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"删除定时任务失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 暂停定时任务
        /// </summary>
        public async Task<bool> PauseScheduledTaskAsync(string taskId)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return false;

                // 暂停Quartz任务
                var triggerKey = new TriggerKey($"workflow_trigger_{taskId}");
                await _scheduler.PauseTrigger(triggerKey);

                // 更新状态
                task.Status = 0; // 暂停
                task.UpdateBy = _currentUser.UserId.ToString();
                task.UpdateTime = DateTime.Now;
                await GetScheduledTaskRepository().UpdateAsync(task);

                _logger.Info($"定时任务暂停成功，ID: {taskId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"暂停定时任务失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 恢复定时任务
        /// </summary>
        public async Task<bool> ResumeScheduledTaskAsync(string taskId)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return false;

                // 恢复Quartz任务
                var triggerKey = new TriggerKey($"workflow_trigger_{taskId}");
                await _scheduler.ResumeTrigger(triggerKey);

                // 更新状态
                task.Status = 1; // 启用
                task.UpdateBy = _currentUser.UserId.ToString();
                task.UpdateTime = DateTime.Now;
                await GetScheduledTaskRepository().UpdateAsync(task);

                _logger.Info($"定时任务恢复成功，ID: {taskId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"恢复定时任务失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取定时任务列表
        /// </summary>
        public async Task<HbtPagedResult<HbtWorkflowScheduledTaskDto>> GetScheduledTasksAsync(HbtWorkflowScheduledTaskQueryDto query)
        {
            try
            {
                var list = await GetScheduledTaskRepository().GetListAsync(x =>
                    (query.Status == null || x.Status == query.Status) &&
                    (string.IsNullOrEmpty(query.TaskName) || x.QuartzName.Contains(query.TaskName))
                );

                var total = list.Count;
                var pagedList = list.Skip((query.PageIndex - 1) * query.PageSize).Take(query.PageSize).ToList();

                var dtoList = pagedList.Select(x => new HbtWorkflowScheduledTaskDto
                {
                    Id = x.Id.ToString(),
                    TaskName = x.QuartzName,
                    TaskType = x.QuartzType,
                    CronExpression = x.QuartzCronExpression,
                    WorkflowInstanceId = 0, // 从QuartzExecuteParams中解析
                    WorkflowSchemeId = 0, // 从QuartzExecuteParams中解析
                    NodeId = "", // 从QuartzExecuteParams中解析
                    NodeName = "", // 从QuartzExecuteParams中解析
                    TaskData = JsonConvert.DeserializeObject<Dictionary<string, object>>(x.QuartzExecuteParams ?? "{}"),
                    Status = x.Status,
                    NextRunTime = x.QuartzNextRunTime
                }).ToList();

                return new HbtPagedResult<HbtWorkflowScheduledTaskDto>
                {
                    TotalNum = total,
                    Rows = dtoList
                };
            }
            catch (Exception ex)
            {
                _logger.Error($"获取定时任务列表失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 获取定时任务详情
        /// </summary>
        public async Task<HbtWorkflowScheduledTaskDto?> GetScheduledTaskAsync(string taskId)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return null;

                return new HbtWorkflowScheduledTaskDto
                {
                    Id = task.Id.ToString(),
                    TaskName = task.QuartzName,
                    TaskType = task.QuartzType,
                    CronExpression = task.QuartzCronExpression,
                    WorkflowInstanceId = 0, // 从QuartzExecuteParams中解析
                    WorkflowSchemeId = 0, // 从QuartzExecuteParams中解析
                    NodeId = "", // 从QuartzExecuteParams中解析
                    NodeName = "", // 从QuartzExecuteParams中解析
                    TaskData = JsonConvert.DeserializeObject<Dictionary<string, object>>(task.QuartzExecuteParams ?? "{}"),
                    Status = task.Status,
                    NextRunTime = task.QuartzNextRunTime
                };
            }
            catch (Exception ex)
            {
                _logger.Error($"获取定时任务详情失败: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 立即执行定时任务
        /// </summary>
        public async Task<bool> ExecuteScheduledTaskNowAsync(string taskId)
        {
            try
            {
                var task = await GetScheduledTaskRepository().GetByIdAsync(long.Parse(taskId));
                if (task == null)
                    return false;

                // 立即执行任务
                var jobKey = new JobKey($"workflow_task_{taskId}");
                var jobData = new JobDataMap
                {
                    { "taskId", taskId }
                };

                await _scheduler.TriggerJob(jobKey, jobData);

                _logger.Info($"定时任务立即执行成功，ID: {taskId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"立即执行定时任务失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 检查工作流超时
        /// </summary>
        public async Task<bool> CheckWorkflowTimeoutAsync(long instanceId)
        {
            try
            {
                var instance = await GetInstanceRepository().GetByIdAsync(instanceId);
                if (instance == null)
                    return false;

                var timeoutConfig = await GetTimeoutConfigAsync(instance.SchemeId);
                if (timeoutConfig == null)
                    return false;

                var timeoutDuration = TimeSpan.FromMinutes(timeoutConfig.TimeoutMinutes);
                var elapsed = DateTime.Now - (instance.StartTime ?? DateTime.Now);

                return elapsed > timeoutDuration;
            }
            catch (Exception ex)
            {
                _logger.Error($"检查工作流超时失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 处理工作流超时
        /// </summary>
        public async Task<bool> HandleWorkflowTimeoutAsync(long instanceId, string timeoutAction)
        {
            try
            {
                var instance = await GetInstanceRepository().GetByIdAsync(instanceId);
                if (instance == null)
                    return false;

                switch (timeoutAction.ToLower())
                {
                    case "auto_approve":
                        // 自动审批通过
                        await _workflowEngine.ApproveAsync(new HbtWorkflowApproveDto
                        {
                            InstanceId = instanceId,
                            NodeId = instance.CurrentNodeId ?? "",
                            OperType = 1, // 同意
                            OperOpinion = "系统自动审批（超时处理）"
                        });
                        break;

                    case "auto_reject":
                        // 自动拒绝
                        await _workflowEngine.ApproveAsync(new HbtWorkflowApproveDto
                        {
                            InstanceId = instanceId,
                            NodeId = instance.CurrentNodeId ?? "",
                            OperType = 2, // 拒绝
                            OperOpinion = "系统自动拒绝（超时处理）"
                        });
                        break;

                    case "escalate":
                        // 升级处理
                        await EscalateWorkflowAsync(instanceId);
                        break;

                    default:
                        // 默认暂停
                        await _workflowEngine.SuspendAsync(instanceId, "工作流超时，系统自动暂停");
                        break;
                }

                _logger.Info($"工作流超时处理成功，实例ID: {instanceId}, 动作: {timeoutAction}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"处理工作流超时失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取超时配置
        /// </summary>
        public async Task<HbtWorkflowTimeoutConfigDto?> GetTimeoutConfigAsync(long schemeId)
        {
            try
            {
                var scheme = await GetSchemeRepository().GetByIdAsync(schemeId);
                if (scheme == null)
                    return null;

                // 从流程配置中解析超时配置
                var config = JsonConvert.DeserializeObject<HbtWorkflowConfigModel>(scheme.SchemeConfig);
                if (config?.TimeoutConfig != null)
                {
                    return new HbtWorkflowTimeoutConfigDto
                    {
                        TimeoutMinutes = config.TimeoutConfig.TimeoutMinutes,
                        TimeoutAction = config.TimeoutConfig.TimeoutAction,
                        EscalationLevels = config.TimeoutConfig.EscalationLevels.Select(x => new HbtWorkflowEscalationLevelDto
                        {
                            Level = x.Level,
                            TimeoutMinutes = x.TimeoutMinutes,
                            Action = x.Action,
                            ApproverIds = x.ApproverIds
                        }).ToList()
                    };
                }

                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"获取超时配置失败: {ex.Message}", ex);
                return null;
            }
        }

        #region 私有方法

        /// <summary>
        /// 初始化调度器
        /// </summary>
        private async Task InitializeSchedulerAsync()
        {
            try
            {
                _scheduler = await _schedulerFactory.GetScheduler();
                await _scheduler.Start();

                // 恢复所有启用的定时任务
                var enabledTasks = await GetScheduledTaskRepository().GetListAsync(x => x.Status == 1);
                foreach (var task in enabledTasks)
                {
                    await RestoreScheduledTaskAsync(task);
                }

                _logger.Info("工作流定时任务调度器初始化成功");
            }
            catch (Exception ex)
            {
                _logger.Error($"初始化调度器失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 恢复定时任务
        /// </summary>
        private async Task RestoreScheduledTaskAsync(HbtQuartz task)
        {
            try
            {
                var jobKey = new JobKey($"workflow_task_{task.Id}");
                var triggerKey = new TriggerKey($"workflow_trigger_{task.Id}");

                var job = JobBuilder.Create<HbtWorkflowScheduledJob>()
                    .WithIdentity(jobKey)
                    .UsingJobData("taskId", task.Id.ToString())
                    .Build();

                var trigger = TriggerBuilder.Create()
                    .WithIdentity(triggerKey)
                    .WithCronSchedule(task.QuartzCronExpression)
                    .Build();

                await _scheduler.ScheduleJob(job, trigger);
            }
            catch (Exception ex)
            {
                _logger.Error($"恢复定时任务失败，ID: {task.Id}, 错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取下次运行时间
        /// </summary>
        private DateTime? GetNextRunTime(string cronExpression)
        {
            try
            {
                var cronTrigger = TriggerBuilder.Create()
                    .WithCronSchedule(cronExpression)
                    .Build();
                return cronTrigger.GetNextFireTimeUtc()?.LocalDateTime;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 升级工作流
        /// </summary>
        private Task EscalateWorkflowAsync(long instanceId)
        {
            try
            {
                // 实现升级逻辑，例如通知上级领导
                _logger.Info($"工作流升级处理，实例ID: {instanceId}");
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger.Error($"工作流升级处理失败: {ex.Message}", ex);
                return Task.FromException(ex);
            }
        }

        /// <summary>
        /// 获取定时任务仓储
        /// </summary>
        private IHbtRepository<HbtQuartz> GetScheduledTaskRepository()
        {
            return _repositoryFactory.GetWorkflowRepository<HbtQuartz>();
        }

        /// <summary>
        /// 获取实例仓储
        /// </summary>
        private IHbtRepository<HbtInstance> GetInstanceRepository()
        {
            return _repositoryFactory.GetWorkflowRepository<HbtInstance>();
        }

        /// <summary>
        /// 获取方案仓储
        /// </summary>
        private IHbtRepository<HbtScheme> GetSchemeRepository()
        {
            return _repositoryFactory.GetWorkflowRepository<HbtScheme>();
        }

        #endregion
    }

    /// <summary>
    /// 工作流定时任务Job
    /// </summary>
    public class HbtWorkflowScheduledJob : IJob
    {
        /// <summary>
        /// 执行定时任务
        /// </summary>
        /// <param name="context">作业执行上下文</param>
        /// <returns>异步任务</returns>
        public async Task Execute(IJobExecutionContext context)
        {
            var taskId = context.JobDetail.JobDataMap.GetString("taskId");
            // 这里实现具体的任务执行逻辑
            await Task.CompletedTask;
        }
    }

    /// <summary>
    /// 工作流配置模型
    /// </summary>
    public class HbtWorkflowConfigModel
    {
        /// <summary>
        /// 超时配置
        /// </summary>
        public HbtTimeoutConfig? TimeoutConfig { get; set; }
    }

    /// <summary>
    /// 超时配置
    /// </summary>
    public class HbtTimeoutConfig
    {
        /// <summary>
        /// 超时分钟数
        /// </summary>
        public int TimeoutMinutes { get; set; }
        
        /// <summary>
        /// 超时动作
        /// </summary>
        public string TimeoutAction { get; set; } = string.Empty;
        
        /// <summary>
        /// 升级级别列表
        /// </summary>
        public List<HbtEscalationLevel> EscalationLevels { get; set; } = new();
    }

    /// <summary>
    /// 升级级别
    /// </summary>
    public class HbtEscalationLevel
    {
        /// <summary>
        /// 升级级别
        /// </summary>
        public int Level { get; set; }
        
        /// <summary>
        /// 超时分钟数
        /// </summary>
        public int TimeoutMinutes { get; set; }
        
        /// <summary>
        /// 动作
        /// </summary>
        public string Action { get; set; } = string.Empty;
        
        /// <summary>
        /// 审批人ID列表
        /// </summary>
        public List<long> ApproverIds { get; set; } = new();
    }
}
